import tkinter as tk
from tkinter import ttk, filedialog, messagebox
from typing import Callable
import os
import json
import sys
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from utils.knowledge_base import KnowledgeBase


class RoleSettings:
    """角色设置界面"""
    
    def __init__(self, parent_frame, config_manager=None):
        self.parent_frame = parent_frame
        self.config_manager = config_manager
        
        # 变量
        self.role_var = None
        self.system_prompt_text = None
        self.knowledge_base_var = None
        self.knowledge_base_list = None
        self.knowledge_preview_text = None
        
        # 知识库管理
        self.knowledge_bases = {}  # 存储各角色的知识库
        self.current_knowledge_base = None
        self.knowledge_base_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "knowledge_base")
        
        # 回调函数
        self.on_role_change = None
        self.on_save_settings = None
        
        self.setup_role_settings_interface()
        self.load_knowledge_bases()
    
    def setup_role_settings_interface(self):
        """设置角色设置界面"""
        # 创建滚动框架
        canvas = tk.Canvas(self.parent_frame)
        scrollbar = ttk.Scrollbar(self.parent_frame, orient="vertical", command=canvas.yview)
        scrollable_frame = ttk.Frame(canvas)
        
        scrollable_frame.bind(
            "<Configure>",
            lambda e: canvas.configure(scrollregion=canvas.bbox("all"))
        )
        
        canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")
        canvas.configure(yscrollcommand=scrollbar.set)
        
        canvas.pack(side="left", fill="both", expand=True)
        scrollbar.pack(side="right", fill="y")
        
        # 角色选择设置
        self.setup_role_selection(scrollable_frame)
        
        # 系统提示设置
        self.setup_system_prompt(scrollable_frame)
        
        # 知识库设置
        self.setup_knowledge_base(scrollable_frame)
        
        # 保存按钮
        ttk.Button(scrollable_frame, text="保存角色设置", command=self._on_save_settings).pack(pady=10)
    
    def setup_role_selection(self, parent):
        """设置角色选择区域"""
        role_frame = ttk.LabelFrame(parent, text="角色选择", padding="10")
        role_frame.pack(fill=tk.X, pady=(0, 10))
        role_frame.columnconfigure(1, weight=1)
        
        ttk.Label(role_frame, text="选择角色:").grid(row=0, column=0, sticky=tk.W, pady=(0, 5))
        self.role_var = tk.StringVar(value="助手")
        
        # 从配置文件获取角色列表
        role_names = []
        if self.config_manager:
            role_names = self.config_manager.get_role_names_from_config()
        
        if not role_names:
            role_names = ["助手", "专家", "老师", "朋友", "顾问"]
        
        role_combo = ttk.Combobox(role_frame, textvariable=self.role_var, 
                                 values=role_names, 
                                 state="readonly", width=20)
        role_combo.grid(row=0, column=1, sticky=tk.W, pady=(0, 5))
        role_combo.bind('<<ComboboxSelected>>', lambda e: self._on_role_change())
        
        # 角色描述
        role_hint = ttk.Label(role_frame, text="选择角色将自动更新系统提示词和知识库", 
                             font=('TkDefaultFont', 8), foreground='gray')
        role_hint.grid(row=1, column=1, sticky=tk.W, pady=(0, 5))
    
    def setup_system_prompt(self, parent):
        """设置系统提示区域"""
        prompt_frame = ttk.LabelFrame(parent, text="系统提示词", padding="10")
        prompt_frame.pack(fill=tk.X, pady=(0, 10))
        
        # 添加说明文字
        prompt_hint = ttk.Label(prompt_frame, text="定义AI角色的行为和回答风格", 
                               font=('TkDefaultFont', 8), foreground='gray')
        prompt_hint.pack(anchor=tk.W, pady=(0, 5))
        
        self.system_prompt_text = tk.Text(prompt_frame, height=6, wrap=tk.WORD, font=('Consolas', 9))
        self.system_prompt_text.pack(fill=tk.X)
        self.system_prompt_text.insert(1.0, "你是一个友善的AI助手，请用中文回答问题。")
        
        # 预设模板按钮
        template_frame = ttk.Frame(prompt_frame)
        template_frame.pack(fill=tk.X, pady=(5, 0))
        
        ttk.Button(template_frame, text="使用默认模板", command=self.use_default_template).pack(side=tk.LEFT, padx=(0, 5))
        ttk.Button(template_frame, text="清空", command=self.clear_prompt).pack(side=tk.LEFT)
    
    def setup_knowledge_base(self, parent):
        """设置知识库区域"""
        kb_frame = ttk.LabelFrame(parent, text="角色知识库", padding="10")
        kb_frame.pack(fill=tk.X, pady=(0, 10))
        
        # 知识库说明
        kb_hint = ttk.Label(kb_frame, text="为角色配置专属知识库，优先匹配知识库内容回答问题", 
                           font=('TkDefaultFont', 8), foreground='gray')
        kb_hint.pack(anchor=tk.W, pady=(0, 5))
        
        # 知识库选择
        kb_select_frame = ttk.Frame(kb_frame)
        kb_select_frame.pack(fill=tk.X, pady=(0, 5))
        
        ttk.Label(kb_select_frame, text="知识库文件:").pack(side=tk.LEFT)
        self.knowledge_base_var = tk.StringVar(value="未选择")
        kb_label = ttk.Label(kb_select_frame, textvariable=self.knowledge_base_var, 
                            font=('TkDefaultFont', 8), foreground='blue')
        kb_label.pack(side=tk.LEFT, padx=(5, 10))
        
        ttk.Button(kb_select_frame, text="选择文件", command=self.select_knowledge_base).pack(side=tk.LEFT, padx=(0, 5))
        ttk.Button(kb_select_frame, text="创建新知识库", command=self.create_knowledge_base).pack(side=tk.LEFT, padx=(0, 5))
        ttk.Button(kb_select_frame, text="编辑知识库", command=self.edit_knowledge_base).pack(side=tk.LEFT, padx=(0, 5))
        ttk.Button(kb_select_frame, text="删除知识库", command=self.delete_knowledge_base).pack(side=tk.LEFT)
        
        # 知识库内容预览
        preview_frame = ttk.LabelFrame(kb_frame, text="知识库预览", padding="5")
        preview_frame.pack(fill=tk.X, pady=(10, 0))
        
        # 知识库列表
        list_frame = ttk.Frame(preview_frame)
        list_frame.pack(fill=tk.X, pady=(0, 5))
        
        ttk.Label(list_frame, text="问答条目:").pack(anchor=tk.W)
        
        # 创建列表框和滚动条
        list_scroll_frame = ttk.Frame(list_frame)
        list_scroll_frame.pack(fill=tk.X, pady=(5, 0))
        
        self.knowledge_base_list = tk.Listbox(list_scroll_frame, height=4, font=('TkDefaultFont', 8))
        kb_scrollbar = ttk.Scrollbar(list_scroll_frame, orient="vertical", command=self.knowledge_base_list.yview)
        self.knowledge_base_list.configure(yscrollcommand=kb_scrollbar.set)
        
        self.knowledge_base_list.pack(side=tk.LEFT, fill=tk.X, expand=True)
        kb_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        
        self.knowledge_base_list.bind('<<ListboxSelect>>', self.on_knowledge_item_select)
        
        # 知识库内容详情
        detail_frame = ttk.Frame(preview_frame)
        detail_frame.pack(fill=tk.X, pady=(5, 0))
        
        ttk.Label(detail_frame, text="答案内容:").pack(anchor=tk.W)
        self.knowledge_preview_text = tk.Text(detail_frame, height=3, wrap=tk.WORD, 
                                             font=('TkDefaultFont', 8), state=tk.DISABLED)
        self.knowledge_preview_text.pack(fill=tk.X, pady=(5, 0))
    
    def load_knowledge_bases(self):
        """加载所有角色的知识库"""
        if not os.path.exists(self.knowledge_base_dir):
            os.makedirs(self.knowledge_base_dir)
        
        self.knowledge_bases = {}
        # 使用目录模式加载知识库，支持向量数据库功能
        try:
            self.knowledge_bases = KnowledgeBase.load_all_from_directory(self.knowledge_base_dir)
        except Exception as e:
            print(f"加载知识库失败: {e}")
            # 回退到逐个文件加载
            self.knowledge_bases = {}
            for filename in os.listdir(self.knowledge_base_dir):
                if filename.endswith('.json'):
                    role_name = filename[:-5]  # 移除.json扩展名
                    kb_path = os.path.join(self.knowledge_base_dir, filename)
                    try:
                        self.knowledge_bases[role_name] = KnowledgeBase(file_path=kb_path)
                    except Exception as e:
                        print(f"加载知识库 {filename} 失败: {e}")
    
    def select_knowledge_base(self):
        """选择知识库文件"""
        file_path = filedialog.askopenfilename(
            title="选择知识库文件",
            initialdir=self.knowledge_base_dir,
            filetypes=[("JSON files", "*.json"), ("All files", "*.*")]
        )
        if file_path:
            # 重新加载知识库
            self.load_knowledge_bases()
            self.update_knowledge_base_display()
    
    def create_knowledge_base(self):
        """创建新的知识库"""
        role = self.role_var.get()
        if not role:
            messagebox.showwarning("警告", "请先选择角色")
            return
        
        kb_filename = f"{role}.json"
        kb_path = os.path.join(self.knowledge_base_dir, kb_filename)
        
        # 创建默认知识库结构
        default_kb = {
            "name": f"{role}知识库",
            "description": f"{role}角色的专用知识库",
            "qa_pairs": [
                {
                    "question": "示例问题",
                    "answer": "这是一个示例回答，请编辑或删除此条目。"
                }
            ]
        }
        
        try:
            with open(kb_path, 'w', encoding='utf-8') as f:
                json.dump(default_kb, f, ensure_ascii=False, indent=2)
            
            self.load_knowledge_bases()
            self.update_knowledge_base_display()
            messagebox.showinfo("成功", f"已创建知识库: {kb_filename}")
        except Exception as e:
            messagebox.showerror("错误", f"创建知识库失败: {e}")
    
    def edit_knowledge_base(self):
        """编辑知识库"""
        role = self.role_var.get()
        if not role:
            messagebox.showwarning("警告", "请先选择角色")
            return
        
        kb_path = os.path.join(self.knowledge_base_dir, f"{role}.json")
        if not os.path.exists(kb_path):
            messagebox.showwarning("警告", f"角色 {role} 的知识库不存在，请先创建")
            return
        
        # 使用系统默认编辑器打开
        try:
            if os.name == 'nt':  # Windows
                os.startfile(kb_path)
            elif os.name == 'posix':  # macOS/Linux
                os.system(f'open "{kb_path}"')
        except Exception as e:
            messagebox.showerror("错误", f"打开编辑器失败: {e}")
    
    def delete_knowledge_base(self):
        """删除知识库"""
        role = self.role_var.get()
        if not role:
            messagebox.showwarning("警告", "请先选择角色")
            return
        
        kb_path = os.path.join(self.knowledge_base_dir, f"{role}.json")
        if not os.path.exists(kb_path):
            messagebox.showwarning("警告", f"角色 {role} 的知识库不存在")
            return
        
        if messagebox.askyesno("确认", f"确定要删除角色 {role} 的知识库吗？此操作不可撤销。"):
            try:
                os.remove(kb_path)
                self.load_knowledge_bases()
                self.update_knowledge_base_display()
                messagebox.showinfo("成功", "知识库已删除")
            except Exception as e:
                messagebox.showerror("错误", f"删除知识库失败: {e}")
    
    def update_knowledge_base_display(self):
        """更新知识库显示"""
        role = self.role_var.get()
        if role in self.knowledge_bases:
            kb_filename = f"{role}.json"
            self.knowledge_base_var.set(kb_filename)
            
            # 显示知识库内容
            try:
                kb = self.knowledge_bases[role]
                if hasattr(kb, 'data') and 'qa_pairs' in kb.data:
                    # 更新问答列表
                    self.knowledge_base_list.delete(0, tk.END)
                    for qa in kb.data['qa_pairs']:
                        question = qa.get('question', '无问题')
                        self.knowledge_base_list.insert(tk.END, question)
                    
                    # 清空预览
                    self.knowledge_preview_text.config(state=tk.NORMAL)
                    self.knowledge_preview_text.delete(1.0, tk.END)
                    self.knowledge_preview_text.insert(1.0, f"知识库: {kb.data.get('name', role + '知识库')}\\n描述: {kb.data.get('description', '无描述')}\\n问答对数量: {len(kb.data['qa_pairs'])}")
                    self.knowledge_preview_text.config(state=tk.DISABLED)
                else:
                    self.knowledge_base_list.delete(0, tk.END)
                    self.knowledge_preview_text.config(state=tk.NORMAL)
                    self.knowledge_preview_text.delete(1.0, tk.END)
                    self.knowledge_preview_text.insert(1.0, "知识库格式错误或为空")
                    self.knowledge_preview_text.config(state=tk.DISABLED)
            except Exception as e:
                self.knowledge_base_list.delete(0, tk.END)
                self.knowledge_preview_text.config(state=tk.NORMAL)
                self.knowledge_preview_text.delete(1.0, tk.END)
                self.knowledge_preview_text.insert(1.0, f"加载知识库内容失败: {e}")
                self.knowledge_preview_text.config(state=tk.DISABLED)
        else:
            self.knowledge_base_var.set("未配置")
            self.knowledge_base_list.delete(0, tk.END)
            self.knowledge_preview_text.config(state=tk.NORMAL)
            self.knowledge_preview_text.delete(1.0, tk.END)
            self.knowledge_preview_text.insert(1.0, "该角色暂无知识库")
            self.knowledge_preview_text.config(state=tk.DISABLED)
    
    def on_knowledge_item_select(self, event):
        """知识库条目选择事件"""
        selection = self.knowledge_base_list.curselection()
        if not selection:
            return
        
        role = self.role_var.get()
        if role not in self.knowledge_bases:
            return
        
        try:
            kb = self.knowledge_bases[role]
            if hasattr(kb, 'data') and 'qa_pairs' in kb.data:
                qa_index = selection[0]
                if qa_index < len(kb.data['qa_pairs']):
                    qa = kb.data['qa_pairs'][qa_index]
                    answer = qa.get('answer', '无答案')
                    
                    self.knowledge_preview_text.config(state=tk.NORMAL)
                    self.knowledge_preview_text.delete(1.0, tk.END)
                    self.knowledge_preview_text.insert(1.0, answer)
                    self.knowledge_preview_text.config(state=tk.DISABLED)
        except Exception as e:
            self.knowledge_preview_text.config(state=tk.NORMAL)
            self.knowledge_preview_text.delete(1.0, tk.END)
            self.knowledge_preview_text.insert(1.0, f"显示答案失败: {e}")
            self.knowledge_preview_text.config(state=tk.DISABLED)
    
    def use_default_template(self):
        """使用默认模板"""
        role = self.role_var.get()
        prompt = self.get_role_system_prompt(role)
        self.system_prompt_text.delete(1.0, tk.END)
        self.system_prompt_text.insert(1.0, prompt)
    
    def clear_prompt(self):
        """清空提示词"""
        self.system_prompt_text.delete(1.0, tk.END)
    
    def get_role_system_prompt(self, role: str) -> str:
        """根据角色获取预设的系统提示词"""
        # 优先从配置文件获取
        if self.config_manager:
            roles_config = self.config_manager.get_roles_from_config()
            if role in roles_config and 'system_prompt' in roles_config[role]:
                return roles_config[role]['system_prompt']
        
        # 如果配置文件中没有，使用默认的
        role_prompts = {
            "助手": "你是一个友善的AI助手，请用中文回答问题。",
            "专家": "你是一个专业的技术专家，具有深厚的知识背景，请提供准确、详细的专业建议。",
            "老师": "你是一个耐心的老师，善于解释复杂概念，请用通俗易懂的方式回答问题。",
            "朋友": "你是一个亲切的朋友，以轻松友好的语调交流，给出实用的建议和支持。",
            "顾问": "你是一个专业的顾问，善于分析问题并给出该问题的答案，请给出结构化的建议。"
        }
        return role_prompts.get(role, role_prompts["助手"])
    
    def update_system_prompt_for_role(self, role: str):
        """根据角色更新系统提示词"""
        if self.system_prompt_text:
            prompt = self.get_role_system_prompt(role)
            self.system_prompt_text.delete(1.0, tk.END)
            self.system_prompt_text.insert(1.0, prompt)
    
    def get_settings(self) -> dict:
        """获取角色设置"""
        return {
            'role': self.role_var.get() if self.role_var else "助手",
            'system_prompt': self.system_prompt_text.get(1.0, tk.END).strip() if self.system_prompt_text else ""
        }
    
    def load_settings(self, settings: dict):
        """加载角色设置"""
        if self.role_var and 'role' in settings:
            self.role_var.set(settings['role'])
            self._on_role_change()
        
        if self.system_prompt_text and 'system_prompt' in settings:
            self.system_prompt_text.delete(1.0, tk.END)
            # 处理None值
            prompt = settings['system_prompt'] or ""
            self.system_prompt_text.insert(1.0, prompt)
    
    def set_callbacks(self, on_role_change: Callable[[], None], on_save_settings: Callable[[], None]):
        """设置回调函数"""
        self.on_role_change = on_role_change
        self.on_save_settings = on_save_settings
    
    def _on_role_change(self):
        """角色改变事件"""
        role = self.role_var.get()
        self.update_system_prompt_for_role(role)
        self.update_knowledge_base_display()
        
        if self.on_role_change:
            self.on_role_change()
    
    def _on_save_settings(self):
        """保存设置事件"""
        if self.on_save_settings:
            self.on_save_settings()
    
    def get_knowledge_base_for_role(self, role: str):
        """获取指定角色的知识库"""
        return self.knowledge_bases.get(role, None)